package stage_1_module_2.code.homework_2;

import java.util.Scanner;

/*****
 * 编程实现控制台版并支持两人对战的五子棋游戏。 
（1）绘制棋盘 - 写一个成员方法实现 
（2）提示黑方和白方分别下棋并重新绘制棋盘 - 写一个成员方法实现。 
（3）每当一方下棋后判断是否获胜 - 写一个成员方法实现。 
（4）提示： 采用二维数组来模拟并描述棋盘，棋盘如下
 * 
 * 解题思路:
 * 1.分别声明二维数组black,white保存黑白子的位置，黑子为-1，白子为1
 * 2.绘制棋盘时，循环每个位置检查是否有黑白子，有则打印1或者-1，无则打印0
 * 3.获取落子的行列数，判断是否在0~15范围内，并且检查是否已经落子
 * 4.有效落子后，检查当前棋手该落子点行、列、左右对角线是否达成5子及以上
 * 5.是否获胜的检查方法依赖该子往前连续子数+1+往后连续子数
 * 
 * 
 */
public class homework_2 {
    public static int  WHITE = 1;
    public static int  BLACK = -1;
    public static int[][] black = new int[16][16];
    public static int[][] white = new int[16][16];
    public static boolean order = false;
    public static boolean over = false;
    public static Scanner sc = new Scanner(System.in);
    public static int winner = 0;
    public static void main(String[] args) {
        while (!over) {
            play();
        }
        System.out.printf("恭喜%s获胜\n",winner == WHITE ? "白方" : "黑方");
        sc.close();
    }

    public static int[] getInput() {
        int[] in = new int[2];
        while (true) {
            int v = sc.nextInt();
            if (v < 0 || v > 15) {
                System.out.println("请重新输入，行范围必须为0~15范围内");
                continue;
            }
             int h = sc.nextInt();
            if (h < 0 || h > 15) {
                System.out.println("请重新输入，列范围必须为0~15范围内");
                continue;
            }
            // 检查是否占用
            if (black[v][h] != 0) {
                System.out.println("请重新输入，黑子已占");
                continue;
            }
            if (white[v][h] != 0) {
                System.out.println("请重新输入，白子已占");
                continue;
            }
            // 落子有效
            in[0] = v;
            in[1] = h;
            break;
        }
        return in;
    }

    public static void play() {
        String player = order ? "白方" : "黑方";
        System.out.println(player+"请下子，分别输入行，列的整数，必须为0~15范围内:");
        int[] in = getInput();
        int v = in[0], h = in[1];
        if (order) {
            // 白子下
            white[v][h] = WHITE;
            isWin(WHITE, v, h);
        } else {
            // 黑子下
            black[v][h] = BLACK;
            isWin(BLACK, v, h);
        }
        order = !order;
        draw();
    }

    /**
     * 判断是否棋手获胜，当前子水平、垂直、左上、右上对角线4个角度，任何一个包含连续5个同颜色棋子则为获胜
     * @param player
     * @param v
     * @param h
     * @return
     */
    public static boolean isWin( int player,  int v,  int h) {
        if (checkV(player, v, h) || checkH(player, v, h) || checkLx(player, v, h) || checkRx(player, v, h)) {
            over = true;
            winner = player;
            return true;
        }
        return false;
    }

    /**
     * 计算当前点水平方向连续数
     * 
     * @param player
     * @param v
     * @param h
     * @return
     */
    public static boolean checkV( int player,  int v,  int h) {
         int[][] check = (player == WHITE) ? white : black;
         int flag = (player == WHITE) ? WHITE : BLACK;
        int sc = 0, gc = 0;
        for (int i = h - 1; i >= 0 ; i--) {
            if (check[v][i] == flag) {
                sc++;
            } else {
                break;
            }
        }
        for (int i = h + 1; i <= 15 ; i++) {
            if (check[v][i] == flag) {
                gc++;
            } else {
                break;
            }
        }
        System.out.printf("%s当前棋子水平连续子数:%d\n",player == WHITE ? "白方" : "黑方",sc+gc+1);
        return (sc + gc + 1) >= 5 ? true : false;
    }

    /**
     * 计算当前点垂直方向连续数
     * 
     * @param player
     * @param v
     * @param h
     * @return
     */
    public static boolean checkH( int player,  int v,  int h) {
         int[][] check = (player == WHITE) ? white : black;
         int flag = (player == WHITE) ? WHITE : BLACK;
        int sc = 0, gc = 0;
        for (int i = v - 1; i >= 0 ; i--) {
            if (check[i][h] == flag) {
                sc++;
            } else {
                break;
            }
        }
        for (int i = v + 1; i <= 15 ; i++) {
            if (check[i][h] == flag) {
                gc++;
            } else {
                break;
            }
        }
        System.out.printf("%s当前棋子垂直连续子数:%d\n",player == WHITE ? "白方" : "黑方",sc+gc+1);
        return (sc + gc + 1) >= 5 ? true : false;
    }

    /**
     * 计算当前点左上对角线连续数
     * 
     * @param player
     * @param v
     * @param h
     * @return
     */
    public static boolean checkLx( int player,  int v,  int h) {
         int flag = (player == WHITE) ? WHITE : BLACK;
         int[][] check = (player == WHITE) ? white : black;
        int sc = 0, gc = 0;
        for (int i = v - 1, j = h - 1; i >= 0 && j >= 0; i--, j--) {
            if (check[i][j] == flag) {
                sc++;
            } else {
                break;
            }
        }
        for (int i = v + 1, j = h + 1; i <= 15 && j <= 15; i++, j++) {
            if (check[i][j] == flag) {
                gc++;
            } else {
                break;
            }
        }
        System.out.printf("%s当前棋子左对角线连续子数:%d\n",player == WHITE ? "白方" : "黑方",sc+gc+1);

        return (sc + gc + 1) >= 5 ? true : false;
    }

    /**
     * 计算当前点右上对角线连续数
     * @param player
     * @param v
     * @param h
     * @return
     */
    public static boolean checkRx( int player,  int v,  int h) {
         int flag = (player == WHITE) ? WHITE : BLACK;
         int[][] check = (player == WHITE) ? white : black;
        int sc = 0, gc = 0;
        for (int i = v + 1, j = h - 1; i <= 15 && j >= 0; i++, j--) {
            if (check[i][j] == flag) {
                sc++;
            } else {
                break;
            }
        }
        for (int i = v - 1, j = h + 1; i >= 0 && j <= 15; i--, j++) {
            if (check[i][j] == flag) {
                gc++;
            } else {
                break;
            }
        }
        System.out.printf("%s当前棋子右对角线连续子数:%d\n",player == WHITE ? "白方" : "黑方",sc+gc+1);
        return (sc + gc + 1) >= 5 ? true : false;
    }

    /**
     * 绘制棋盘,黑方输出0，白方触发1，空白输出+
     */
    public static void draw() {
        for (int i = 0; i < 16; i++) {
            for (int j = 0; j < 16; j++) {
                char t = (white[i][j] > 0) ? '1' : (black[i][j] < 0 ? '0' : '+');
                System.out.printf(" "+t);
            }
            System.out.printf("\n");
        }
    }
}
